//singleton
function WebCanvas(e){
	WebObj.call(this);
	this.elem = e;
	this.dragStart = null;
	this.dragTranslate = {x:0, y:0};
	this.pinchStartD = 0;
	this.pinchScale = null;
	this.pinchOrigin = null;
	this.contentPos = null;
	this.content = this.elem.querySelector('.webcanvascontent');

	var upval=this;
	{
		var hl = document.createElement('div');
		this.hl = hl;
		hl.className = 'dockpos';
		hl.style.cursor = 'move';
		var offX, offY;
		_DnD.makeDragDrop(hl, this.elem, function(clientX, clientY, clip){
			//_log.innerHTML='dr';
			_webcanvas.moveObject(upval.select,
				clientX - offX * _webcanvas.scale,
				clientY - offY * _webcanvas.scale);
		}, function (clientX, clientY){
			var ret = _webcanvas.getCanvasPos(
				clientX - offX * _webcanvas.scale,
				clientY - offY * _webcanvas.scale);
			hl.style.left = ret.x+'px';
			hl.style.top = ret.y+'px';
		}, function (clientX, clientY){
			var pos = upval.getCanvasPos(clientX, clientY);
			offX = pos.x - hl.offsetLeft;
			offY = pos.y - hl.offsetTop;
		});
		if (_browser.is_mobile)
			hl.addEventListener('touchstart', function(e){
				e.preventDefault();
				e.stopPropagation();
			},false);
		else
			hl.addEventListener('mousedown', function(e){
				e.stopPropagation();
				//e.preventDefault();
			},false);
		/*
		hl.addEventListener('contextmenu', function(e){
			if (!upval.select) return;
			e.preventDefault();
			Revision.combine({},function(){
				var tmp = upval.select;
				upval.select = null;
				upval.children.remove(tmp);
			});
		});*/
		
		Property(this, 'select', null, true, function(webObj){
			if (hl.parentNode) hl.parentNode.removeChild(hl);
			if (webObj){
				webObj.elem.parentNode.appendChild(hl);
				with(webObj.elem.style){
					hl.style.left = left;
					hl.style.top = top;
					hl.style.width = width;
					hl.style.height = height;
				}
				_propList.displayProp(webObj);
			}
		});
	}
	if (_browser.is_mobile){
		ArrayProperty(this, 'children', true, function(webobj){
			upval.content.appendChild(webobj.elem);
			if (webobj instanceof WebTextBox)
				upval.content.appendChild(webobj.elem_cover);
			webobj._webcanvas_move = {};//undo key for webcanvas move
		},
		function(webobj){
			upval.content.removeChild(webobj.elem);
			if (webobj instanceof WebTextBox)
				upval.content.removeChild(webobj.elem_cover);
		});
		Property(this, 'preview', false, false, function(val){
			if (val){
				upval.select = null;
				var childList = upval.children.getList();
				for (var child in childList){
					if (childList[child] instanceof WebTextBox)
						childList[child].elem_cover.style.display = 'none';
				}
			}else{
				var childList = upval.children.getList();
				for (var child in upval.children.getList()){
					if (childList[child] instanceof WebTextBox)
						childList[child].elem_cover.style.display = 'inherit';
				}
			}
		});
	}else{
		ArrayProperty(this, 'children', true, function(webobj){
			upval.content.appendChild(webobj.elem);
			webobj._webcanvas_move = {};//undo key for webcanvas move
		},
		function(webobj){
			upval.content.removeChild(webobj.elem);
		});
		Property(this, 'preview', false, false, function(val){
			if (val){
				upval.select = null;
			}else{
			}
		});
	}
	
	this.wheel_undokey = {};
	
	Property(this, 'scale', 1, false);
	Property(this, 'translate', {x:0,y:0}, false);
	
	/*this.scale = 1;
	this.translate = {x:0, y:0};*/
	this.movehandler = null;
	//*
	if (_browser.is_mobile){
		var upval = this;
		var touchmove, touchend;
		var oldTranslate, oldScale;
		this.elem.addEventListener('touchstart', function(e){
			//_log.innerHTML='.ts';
			//if (preview) return;
			if (e.targetTouches.length==1){
				e.preventDefault();
				upval._handleMousedown(e.targetTouches[0]);		
			}else if (e.targetTouches.length==2){
				e.preventDefault();
				upval.pinchStart(e.targetTouches[0], e.targetTouches[1]);
			}else return;
			//upval.elem.removeEventListener('touchmove', touchmove);
			//upval.elem.removeEventListener('touchend', touchend);
			oldTranslate = _clone(upval.translate);
			oldScale = upval.scale;
			upval.elem.addEventListener('touchmove', touchmove,false);
			upval.elem.addEventListener('touchend', touchend,false);
		},false);
		touchmove = function(e){
			//_log.innerHTML='.tm';
			if (e.targetTouches.length==1){
				upval.handleMousemove(e.targetTouches[0]);		
			}else if (e.targetTouches.length==2){
				upval.pinching(e.targetTouches[0], e.targetTouches[1]);
			}else return;
		};
		touchend = function(e){
			//_log.innerHTML='.te';
			if (e.touches.length==0){
				with(upval){
					elem.removeEventListener('touchmove', touchmove,false);
					var newTranslate = _clone(translate);
					var newScale = scale;
					var undoFunc = function(){
						//_log.innerHTML='.uds';
						translate = _clone(oldTranslate);
						scale = oldScale;
						adjustTransform();
						//_log.innerHTML='.ude'+scale;
					}
					undoFunc.redo = function(){
						translate = _clone(newTranslate);
						scale = newScale;
						adjustTransform();
					}
					undoFunc.id = meta_scale;
					Revision.applyAction(undoFunc);
					//_log.innerHTML='.undo';
				}
			}
			upval.elem.removeEventListener('touchend', touchend,false);
		};
	}else{
		this.elem.addEventListener('mousedown', this.handleMousedown.bind(this),false);
		_root.addEventListener('mouseup', this.handleMouseup.bind(this),false);
		this.elem.addEventListener(_browser.is_firefox?'DOMMouseScroll':'mousewheel', this.handleMousewheel.bind(this),false);
	}//*/
	this.adjustTransform();
}

_inherit('WebCanvas', WebCanvas, WebObj);

WebCanvas.prototype.invalidate = function(){
	with(this){
		if (meta_scale.isChanged() || meta_translate.isChanged())
			adjustTransform();
	}
}

WebCanvas.prototype._handleMousedown = function(e){
	with(this){
		dragStart = {x: e.clientX, y:e.clientY};
		dragTranslate.x = translate.x;
		dragTranslate.y = translate.y;
	}
}

WebCanvas.prototype.handleMousedown = function(e){
	with(this){
		if (movehandler/* || preview*/)
			return;
		_handleMousedown(e);
		e.preventDefault();
		if (movehandler){
			_root.removeEventListener('mousemove',movehandler,false);
			movehandler = null;			
		}
		movehandler = handleMousemove.bind(this);
		_root.addEventListener('mousemove', movehandler,false);		
	}
}

WebCanvas.prototype.pinchStart = function(p1, p2){
	with(this){
		var delta = {x:p1.clientX-p2.clientX, y:p1.clientY-p2.clientY};
		pinchStartD = Math.sqrt(delta.x*delta.x+delta.y*delta.y);
		pinchScale = scale;
		contentPos = _absPos(this.content);
		pinchOrigin = {x:(p1.clientX+p2.clientX)/2-contentPos.x-translate.x,
			y:(p1.clientY+p2.clientY)/2-contentPos.y-translate.y};
		//_log.innerHTML = pinchOrigin.x+'.'+pinchOrigin.y;
		dragTranslate.x = translate.x;
		dragTranslate.y = translate.y;
	}
}

WebCanvas.prototype.adjustTransform = function(){
	with(this){
		//if (meta_scale.isChanged())
		content.style[_browser.is_firefox?'MozTransform':'-webkit-transform'] =
			'translate('+translate.x+'px,'
			+translate.y+'px)'
			+' scale('+scale+')';
		/*elem.scrollLeft = -translate.x;
		elem.scrollTop = -translate.y;*/
	}
}

WebCanvas.prototype.handleMousemove = function(e){
	with(this){
		translate.x = dragTranslate.x + e.clientX - dragStart.x;
		translate.y = dragTranslate.y + e.clientY - dragStart.y;
		adjustTransform();
	}	
}

WebCanvas.prototype.pinching = function(p1,p2){
	with(this){
		var delta = {x:p1.clientX-p2.clientX, y:p1.clientY-p2.clientY};
		var curD = Math.sqrt(delta.x*delta.x+delta.y*delta.y);
		var scaleChange = (curD / pinchStartD);
		scale = pinchScale * scaleChange;
		var offset = {x:(p1.clientX+p2.clientX)/2-contentPos.x - dragTranslate.x - pinchOrigin.x,
			y:(p1.clientY+p2.clientY)/2-contentPos.y - dragTranslate.y - pinchOrigin.y};
		translate.x = offset.x + dragTranslate.x-(pinchOrigin.x)*(scaleChange-1);
		translate.y = offset.y + dragTranslate.y-(pinchOrigin.y)*(scaleChange-1);
		adjustTransform();
	}
}

WebCanvas.prototype.handleMouseup = function(e){
	with(this){
		if (movehandler){
			_root.removeEventListener('mousemove',movehandler,false);
			movehandler = null;
			{//undo/redo
				var oldTranslate = _clone(dragTranslate);
				var newTranslate = _clone(translate);
				var undoFunc = function(){
					translate = _clone(oldTranslate);
					adjustTransform();
				}
				undoFunc.redo = function(){
					translate = _clone(newTranslate);
					adjustTransform();
				}
				undoFunc.id = meta_translate;
				Revision.applyAction(undoFunc);
			}
		}
	}
}

WebCanvas.prototype.handleMousewheel = function(e){
	with(this){
		//e.wheelDelta/120;
		//_log.innerHTML = e.clientX;
		var delta = _browser.is_firefox?-e.detail/3:e.wheelDelta/120;
		var ori = _absPos(this.content);
		pinchOrigin = {x:e.clientX-ori.x-translate.x,
			y:e.clientY-ori.y-translate.y};
		var scaleChange = (1+delta/10);
		var oldScale = scale;
		var newScale = scale * scaleChange;
		var oldTranslate = _clone(translate);
		var newTranslate = {
			x:translate.x - (pinchOrigin.x)*(scaleChange-1),
			y:translate.y - (pinchOrigin.y)*(scaleChange-1)
		};
		
		var undoFunc = function(){
			scale = oldScale;
			translate = _clone(oldTranslate);
			adjustTransform();
		}
		undoFunc.redo = function(){
			scale = newScale;
			translate = _clone(newTranslate);
			adjustTransform();
		}
		undoFunc.id = wheel_undokey;
		Revision.applyAction(undoFunc);
	}
}

WebCanvas.prototype.getCanvasPos = function(clientX, clientY){
	with(this){
		var pos = _absPos(content);
		return {x:(clientX - pos.x - translate.x)/scale,
			y:(clientY - pos.y - translate.y)/scale};
	}
}

WebCanvas.prototype.createObject = function(obj, clientX, clientY){
	with(this){
		var ret = getCanvasPos(clientX, clientY);
		obj.meta_left.set_norev(ret.x+'px');
		obj.meta_top.set_norev(ret.y+'px');
		children.push(obj);
	}
}

WebCanvas.prototype.removeObject = function(obj){
	var upval = this;
	Revision.combine({},function(){
		var tmp = upval.select;
		upval.select = null;
		upval.children.remove(tmp);
	});
}

WebCanvas.prototype.moveObject = function(obj, clientX, clientY){
	with(this){
		var ret = getCanvasPos(clientX, clientY);
		var oldLeft = obj.left;
		var oldTop = obj.top;
		var newLeft =  ret.x+'px';
		var newTop = ret.y+'px';
		{
			var undoFunc = function(){
				obj.meta_left.set_norev(oldLeft);
				obj.meta_top.set_norev(oldTop);
				if (obj==select) adjustSelect();
			}
			undoFunc.redo = function(){
				obj.meta_left.set_norev(newLeft);
				obj.meta_top.set_norev(newTop);
				if (obj==select) adjustSelect();
			}
			undoFunc.id = obj._webcanvas_move;
			Revision.applyAction(undoFunc);
			//_log.innerHTML = 'dre'+oldLeft+'.'+newLeft;
		}
	}
}

WebCanvas.prototype.adjustSelect = function(){
	with(this){
		hl.style.left = select.left;
		hl.style.top = select.top;
		//_log.innerHTML = '.m'+hl.style.left;
	}
}

//logpush('Finish processing WebCanvas');